package com.sz.biz.logistics.core.service.impl;

import com.google.common.collect.Lists;
import com.sz.biz.common.AbstractVersionEntityService;
import com.sz.biz.common.customer.entity.CusUser;
import com.sz.biz.common.customer.service.CustomerUserService;
import com.sz.biz.logistics.constants.ProductGroupCode;
import com.sz.biz.logistics.core.dto.AllProductGroupDto;
import com.sz.biz.logistics.core.dto.ProductGroupDto;
import com.sz.biz.logistics.core.entity.ProductCustomerRel;
import com.sz.biz.logistics.core.entity.ProductGroup;
import com.sz.biz.logistics.core.service.ProductCustomerRelService;
import com.sz.biz.logistics.core.service.ProductGroupService;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.TreeNode;
import com.sz.common.base.utils.CollectionUtils;
import com.sz.common.base.utils.StringUtils;
import com.sz.common.base.utils.TreeBuilder;
import com.sz.common.core.service.PrincipalUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Function: 产品组ervice <br>
 * Author: penghui.zheng <br>
 * Date: 2017-05-10 16:08:00
 */
@org.springframework.stereotype.Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class ProductGroupServiceImpl extends AbstractVersionEntityService implements ProductGroupService {

    private static final int DEFAULT = 0;
    private static final int ROOT = 0;
    @Autowired
	private ProductCustomerRelService productCustomerRelService;

	@Autowired
	private CustomerUserService customerUserService;

    /**
     * 根据parentId查询产品组信息
     *
     * @param parentId
     */
    @Override
    public List<ProductGroupDto> findByParentId(Integer parentId) {
        ParamData paramData = new ParamData();
        paramData.put("parentId", parentId);
        return dao.findForList("ProductGroupMapper.findByParentId", paramData, ProductGroupDto.class);
    }

    @Override
    public List<ProductGroupDto> findByParentIdCustomer(int parentId) {
        //所有产品组
        List<ProductGroup> productGroupsAll = list();
        // 获取当前登录用户
        CusUser user = customerUserService.findById(PrincipalUtils.getAccountId());
        Set<Integer> productGroupIds = new HashSet<>();
        Integer wbFlag = 0;
        if (null != user) {
            Integer customerId = user.getRefCustomerId();
            List<ProductCustomerRel> productCustomerRelList = productCustomerRelService.findByCustomerId(customerId, false);
            if (!CollectionUtils.isEmpty(productCustomerRelList)) {
                // 白黑名单标志 0:可以看到公共产品和自己设置的白名单产品 1: 白名单(只能看白名单里的产品)； 2： 黑名单(不能看的产品)
                for (ProductCustomerRel productCustomerRel : productCustomerRelList) {
                    wbFlag = productCustomerRel.getWbFlag();
                    // type 0: 产品组； 1： 产品
                    if (productCustomerRel.getType().compareTo(0) == 0 && null != productCustomerRel.getProductGroupId()) {
                        productGroupIds.add(productCustomerRel.getProductGroupId());
                        // 获取产品组的上级
                        findParent(productCustomerRel.getProductGroupId(), productGroupIds, productGroupsAll);
                    }else if (productCustomerRel.getType().compareTo(1) == 0 && !StringUtils.isEmpty(productCustomerRel.getProductGroupLeafId())){
                        productGroupIds.add(productCustomerRel.getProductGroupLeafId());
                        // 获取产品组的上级
                        findParent(productCustomerRel.getProductGroupLeafId(), productGroupIds, productGroupsAll);
                    }
                }
            }
        }
        if (CollectionUtils.isEmpty(productGroupIds)) {
            productGroupIds.add(-1);
        }
        ParamData paramData = new ParamData();
        paramData.put("parentId", parentId);
        paramData.put("productGroupIds", productGroupIds);
        paramData.put("wbFlag", wbFlag);
        return dao.findForList("ProductGroupMapper.findByParentIdCustomer", paramData, ProductGroupDto.class);
    }

	/**
	 * 产品组上级
	 * @param id
	 * @param productGroupIds
	 * @param productGroupsAll
     * @return
	 */
	private void findParent(int id, Set<Integer> productGroupIds, List<ProductGroup> productGroupsAll) {
		ProductGroup productGroup = isExistParentGroup(id, productGroupsAll);
		if (null != productGroup) {
			productGroupIds.add(productGroup.getId());
			findParent(productGroup.getId(), productGroupIds, productGroupsAll);
		}
	}

    /**
     * 产品组是否有父节点
     * @param id
     * @param productGroupsAll
     * @return
     */
	private ProductGroup isExistParentGroup(int id, List<ProductGroup> productGroupsAll){
	    if(!CollectionUtils.isEmpty(productGroupsAll)){
            for(ProductGroup productGroup : productGroupsAll){
                if(0 == productGroup.getId().compareTo(id)){
                    return parentGroupId(productGroup.getParentId(), productGroupsAll);
                }
            }
        }
        return null;
    }

    /**
     * 产品组是否有父节点
     * @param parentId
     * @param productGroupsAll
     * @return
     */
    private ProductGroup parentGroupId(int parentId, List<ProductGroup> productGroupsAll){
        if(!CollectionUtils.isEmpty(productGroupsAll)){
            for(ProductGroup productGroup : productGroupsAll){
                if(0 == productGroup.getId().compareTo(parentId)){
                    return productGroup;
                }
            }
        }
        return null;
    }

	/**
	 * 根据id查询父节点
	 *
	 * @param id
	 * @return
	 */
	@Override
	public ProductGroup findById(Integer id) {
        return (ProductGroup) dao.findForObject("ProductGroupMapper.findById", id);
	}

    @Override
    public List<ProductGroup> findById(List<Integer> ids) {
        List<ProductGroup> productGroups  = new ArrayList<>();
	    if(!CollectionUtils.isEmpty(ids)){
            productGroups=  dao.findForList("ProductGroupMapper.findByIds",ids,ProductGroup.class);
        }
        return productGroups;
    }

    /**
	 * 根据产品组id返回根节点类型
	 *
	 * @param id
	 * @return
	 */
	@Override
	public int findTypeById(Integer id) {
		if (id.equals(DEFAULT)) {
			return ProductGroupCode.LAND_TRANSPORT;
		}
		ProductGroup dto = (ProductGroup) dao.findForObject("ProductGroupMapper.findById", id);
		if (dto != null) {
            if (dto.getParentId().equals(ROOT)) {
                if (dto.getId().equals(ProductGroupCode.SEA_TRANSPORT) ||
                        dto.getId().equals(ProductGroupCode.AIR_TRANSPORT)) {
                    return id;
                }

            }
        }
		 return ProductGroupCode.LAND_TRANSPORT;
	}

	/**
	 * 根据id查询所有节点
	 *
	 * @param id
	 * @return
	 */
	@Override
	public AllProductGroupDto findAllById(Integer id) {
		AllProductGroupDto dto = new AllProductGroupDto();
		ProductGroup productGroup = (ProductGroup) dao.findForObject("ProductGroupMapper.findById", id);
		if (productGroup != null && productGroup.getParentId() > 0) {
			ProductGroup parent = (ProductGroup) dao.findForObject("ProductGroupMapper.findById", productGroup.getParentId());
			if (parent != null) {
				BeanUtils.copyProperties(parent, dto);
				List<ProductGroup> list = new ArrayList<ProductGroup>();
				list.add(productGroup);
				dto.setChildProductGroup(list);
			} else {
				BeanUtils.copyProperties(productGroup, dto);
			}
		}
		return dto;
	}

	/**
	 * 所有产品组
	 *
	 * @param parentId
	 * @param isShowAll
     * @return
	 */
	@Override
	public List<TreeNode> findAll(Integer parentId, Boolean isShowAll) {
        ParamData paramData = new ParamData();
	    if(!isShowAll){
            List<ProductGroup> allProductGroups = Lists.newArrayList();
            List<Integer> parentIds = Lists.newArrayList();
            if(!ObjectUtils.isEmpty(parentId)){
                parentIds.add(parentId);
            }
            //所有私有产品组
            List<ProductGroup> privateProductGroups = privatePopulateGroups(parentIds);
            if(!CollectionUtils.isEmpty(privateProductGroups)){
                allProductGroups.addAll(privateProductGroups);
            }

            //查询所有产品组
            Set<Integer> allGroupIds = new HashSet<>();
            if(!CollectionUtils.isEmpty(allProductGroups)){
                for (ProductGroup productGroup : allProductGroups) {
                    allGroupIds.add(productGroup.getId());
                }
            }else{
                allGroupIds.add(-1);
            }
            paramData.put("groupIds", allGroupIds);
            paramData.put("isPublic", null);
        }
        List<ProductGroup> productGroupsAll = dao.findForList(getSqlName("findAll"), paramData, ProductGroup.class);
        //转换树形结构
        List<TreeNode> nodes = new ArrayList<>();
		setListData(productGroupsAll, nodes);
		return TreeBuilder.buildListToTree(nodes);
	}

    /**
     * 产品组列表
     * @return
     */
    @Override
    public List<ProductGroup> list(){
        ParamData paramData = new ParamData();
       return dao.findForList(getSqlName("findAll"), paramData, ProductGroup.class);
    }

    /**
     * 所有私有产品组
     * @param parentIds
     * @return
     */
	private List<ProductGroup> privatePopulateGroups(List<Integer> parentIds){
        List<ProductGroup> productGroups = Lists.newArrayList();
        List<ProductGroup> children = privatePopulateChildrenGroups(parentIds, false);
        List<ProductGroup> parents = privatePopulateParentGroups(parentIds, false);

        if(!CollectionUtils.isEmpty(children)){
            productGroups.addAll(children);
        }
        if(!CollectionUtils.isEmpty(parents)){
            productGroups.addAll(parents);
        }

        return productGroups;
    }

    /**
     * 所有私有产品组
     * @param parentIds
     * @return
     */
    private List<ProductGroup> privatePopulateParentGroups(List<Integer> parentIds, Boolean isPublic){
        ParamData paramData = new ParamData();
        paramData.put("parentIds", parentIds);
        paramData.put("isPublic", isPublic);
        List<ProductGroup> productGroups = dao.findForList(getSqlName("findAll"), paramData, ProductGroup.class);
        if(!CollectionUtils.isEmpty(productGroups)){
            List<Integer> groupIds = Lists.newArrayList();
            for(ProductGroup productGroup : productGroups){
                groupIds.add(productGroup.getParentId());
            }
            if(null == productGroups){
                productGroups = Lists.newArrayList();
            }
            productGroups.addAll(populateGroups(groupIds, parentIds));
        }
        return productGroups;
    }

    /**
     * 所有私有产品组
     * @param parentIds
     * @return
     */
    private List<ProductGroup> privatePopulateChildrenGroups(List<Integer> parentIds, Boolean isPublic){
        ParamData paramData = new ParamData();
        paramData.put("parentIds", parentIds);
        paramData.put("isPublic", isPublic);
        List<ProductGroup> productGroups = dao.findForList(getSqlName("findAll"), paramData, ProductGroup.class);
        if(!CollectionUtils.isEmpty(productGroups)){
            List<Integer> parentIdNews = Lists.newArrayList();
            for(ProductGroup productGroup : productGroups){
                parentIdNews.add(productGroup.getId());
            }
            //最上级产品组，获取子产品组
            if(null == productGroups){
                productGroups = Lists.newArrayList();
            }
            productGroups.addAll(privatePopulateChildrenGroups(parentIdNews, null));
        }
        return productGroups;
    }

    /**
     * 根据私有产品找到产品组信息
     * @param leafGroupIds
     * @param parentIds
     * @return
     */
	private List<ProductGroup> populateGroups(List<Integer> leafGroupIds, List<Integer> parentIds){
        ParamData paramData = new ParamData();
        paramData.put("parentIds", parentIds);
        paramData.put("isPublic", null);
        if(!CollectionUtils.isEmpty(leafGroupIds)){
            paramData.put("groupIds", leafGroupIds);
        }
        List<ProductGroup> productGroups = dao.findForList(getSqlName("findAll"), paramData, ProductGroup.class);
        if(!CollectionUtils.isEmpty(productGroups)){
            List<Integer> groupIds = Lists.newArrayList();
            for (ProductGroup productGroup : productGroups) {
                if(productGroup.getParentId() != 0){
                    groupIds.add(productGroup.getParentId());
                }
            }
            if(!CollectionUtils.isEmpty(groupIds)){
                if(null == productGroups){
                    productGroups = Lists.newArrayList();
                }
                productGroups.addAll(populateGroups(groupIds, parentIds));
            }
        }
        return productGroups;
    }

	/**
	 * 产品组list转换为node list
	 *
	 * @param list
	 * @param nodes
	 */
	private void setListData(List<ProductGroup> list, List<TreeNode> nodes) {
		for (ProductGroup productGroup : list) {
			TreeNode treeNode = new TreeNode();
			treeNode.setId(productGroup.getId());
			treeNode.setName(productGroup.getName());
			treeNode.setParentId(productGroup.getParentId());
            treeNode.setIsPublic(productGroup.getPublic());
			nodes.add(treeNode);
		}
	}

	/**
	 * 查询运输类型
	 *
	 * @return
	 */
	@Override
	public List<ProductGroupDto> findTransportType() {
		List<ProductGroupDto> dtos=new ArrayList<ProductGroupDto>();
		ParamData paramData = new ParamData();
		paramData.put("parentId", 0);
		List<ProductGroup> productGroups = dao.findForList(getSqlName("findTransportType"), paramData, ProductGroup.class);
		if (productGroups != null) {
			for (ProductGroup productGroup : productGroups) {
				if (productGroup.getId().equals(1) || productGroup.getId().equals(6)
						|| productGroup.getId().equals(11)) {
					ProductGroupDto dto=new ProductGroupDto();
					BeanUtils.copyProperties(productGroup, dto);
					dtos.add(dto);
				}
			}
		}
		return dtos;
	}

	@Override
	public List<ProductGroup> findAllChild(){
        List<ProductGroup> queryAll = dao.findForList("ProductGroupMapper.queryAllProductGroup", null,
                ProductGroup.class);
        List<ProductGroup> queryChildAll = new ArrayList<>();
        for(int i=0;i<queryAll.size();i++) {
            ProductGroup productGroupDto = queryAll.get(i);
            int k = 0;
            for(int j=0;j<queryAll.size();j++){
                //说明不是同一个数据
                if (queryAll.get(j).getId().intValue() != productGroupDto.getId().intValue()) {
                    if (queryAll.get(j).getParentId() == productGroupDto.getId().intValue()) {
                        k++;
                    }
                }
            }
            if (k == 0) {
                queryChildAll.add(queryAll.get(i));
            }
        }
        queryChildAll.sort((a1 , a2) -> {
            if (a1.getParentId().intValue() == a2.getParentId().intValue()) {
                return a1.getOrdinal().compareTo(a2.getOrdinal());
            }
            else {
                return a1.getParentId().compareTo(a2.getParentId());
            }
        });
        return queryChildAll;
    }

    @Override
	protected String getMapperNamespace() {
		return "ProductGroupMapper";
	}
}
